package com.hxx.controller;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hxx.common.AiMessageChatMemory;
import com.hxx.domain.AiMessage;
import com.hxx.mapper.AiMessgeMapper;
import com.hxx.mapper.AiSessionMapper;
import lombok.SneakyThrows;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.model.Media;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

@RequestMapping("message")
@RestController
public class AiMessageController {
    @Autowired
    private AiMessageChatMemory chatMemory;
    @Autowired
    private ChatModel dashScopeAiChatModel;
    @Autowired
    private  ObjectMapper objectMapper;
    @Autowired
    private AiMessgeMapper messageRepository;

    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private AiSessionMapper aiSessionRepository;

    /**
     * 删除与特定会话相关的聊天历史记录
     * 此方法通过DeleteMapping注解映射到HTTP DELETE请求，请求路径为"/history/{sessionId}"
     * 它接受一个路径变量sessionId，表示要删除聊天历史记录的会话ID
     *
     * @param sessionId 会话ID，用于标识和删除特定会话的聊天历史记录
     */
    @DeleteMapping("history/{sessionId}")
    public void deleteHistory(@PathVariable String sessionId) {
        chatMemory.clear(sessionId);
    }

    /**
     * 消息保存
     *
     * @param input 用户发送的消息/AI回复的消息
     */
    @PostMapping
    public void save(@RequestBody AiMessage input) {
        messageRepository.insert(input);
    }

    /**
     * @param input 消息包含文本信息，会话id，多媒体信息（图片语言）。
     * @return SSE流
     */
    @PostMapping(value = "chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ServerSentEvent<String>> chat(@RequestBody AiMessage input) {
        // MessageChatMemoryAdvisor的三个参数解释。
        // 1. 如果需要存储会话和消息到数据库，自己可以实现ChatMemory接口，这里使用自己实现的AiMessageChatMemory，数据库存储。
        // 2. 传入会话id，MessageChatMemoryAdvisor会根据会话id去查找消息。
        // 3. 只需要携带最近10条消息
        var messageChatMemoryAdvisor = new MessageChatMemoryAdvisor(chatMemory, input.getSessionId(), 10);
        // 获取ChatClient
        return ChatClient.create(dashScopeAiChatModel).prompt()
                .user(promptUserSpec -> {
                    Message message = AiMessageChatMemory.toSpringAiMessage(input);
                    if (message instanceof UserMessage userMessage && !CollectionUtils.isEmpty(userMessage.getMedia())) {
                        // 用户发送的图片/语言
                        Media[] medias = new Media[userMessage.getMedia().size()];
                        promptUserSpec.media(userMessage.getMedia().toArray(medias));
                    }
                    // 用户发送的文本
                    promptUserSpec.text(message.getContent());
                })
                .advisors(messageChatMemoryAdvisor)
                .stream()
                .content()
                .map(chatResponse -> ServerSentEvent.builder(chatResponse)
                        .event("message")
                        .build());
    }
    @SneakyThrows
    public String toJson(ChatResponse response) {
        try {
            return objectMapper.writeValueAsString(response);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }
}
